home *** CD-ROM | disk | FTP | other *** search
- /*==============================================================================
- Project: POV
-
- Version: 3
-
- File: LnkLst.c
-
- Description:
- Routines to handle linked lists
- ------------------------------------------------------------------------------
- Author:
- Eduard [esp] Schwan
- ------------------------------------------------------------------------------
- from Persistence of Vision(tm) Ray Tracer
- Copyright 1996 Persistence of Vision Team
- ------------------------------------------------------------------------------
- NOTICE: This source code file is provided so that users may experiment
- with enhancements to POV-Ray and to port the software to platforms other
- than those supported by the POV-Ray Team. There are strict rules under
- which you are permitted to use this file. The rules are in the file
- named POVLEGAL.DOC which should be distributed with this file. If
- POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- Forum. The latest version of POV-Ray may be found there as well.
-
- This program is based on the popular DKB raytracer version 2.12.
- DKBTrace was originally written by David K. Buck.
- DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- ------------------------------------------------------------------------------
- Change History:
- ==============================================================================*/
-
-
- #define LNKLST_C
-
- #include "LnkLst.h"
-
- #include <types.h> // Ptr
- #include <memory.h> // disposeptr
- #include <StdDef.h>
-
-
- // House keeping
-
- // ------------------------------------------------------------
- LLHeadPtr LLCreateList(short MaxElements)
- {
- LLHeadPtr LL;
-
- // Create new list head record
- LL = (LLHeadPtr)NewPtr(sizeof(LLHeadRec));
-
- // Initialize fields
- if (LL)
- {
- LL->fMaxElements = MaxElements;
- LL->fNumElements = 0;
- LL->fFirstElement = NULL;
- LL->fLastElement = NULL;
- }
-
- // return new LL to user
- return LL;
- } // LLCreateList
-
-
- // ------------------------------------------------------------
- void LLDestroyList(LLHeadPtr LL)
- {
- if (LL)
- {
- // Delete all elements from the list
- LLDeleteAllElements(LL);
-
- // Now delete the header record itself
- DisposePtr((Ptr)LL);
- }
- } // LLDestroyList
-
-
- // ------------------------------------------------------------
- void LLDeleteAllElements(LLHeadPtr LL)
- {
- if (LL)
- {
- // delete each one
- while (LLGetNumElements(LL) > 0)
- {
- LLDeleteElementByIndex(LL, 1);
- }
- }
- } // LLDeleteAllElements
-
-
- // Add
-
- // ------------------------------------------------------------
- void LLAddElementByIndex(LLHeadPtr LL, void * DataPtr, short Index)
- {
- LLElPtr newEl;
- LLElPtr oldEl;
-
- if (LL)
- {
- // allocate a new element
- newEl = (LLElPtr)NewPtr(sizeof(LLElRec));
- // initialize fields
- newEl->fNext = NULL;
- newEl->fPrev = NULL;
- newEl->fData = DataPtr;
- // add it to list
- if (LLGetNumElements(LL) == 0)
- { // add to empty list
- LL->fFirstElement = newEl;
- LL->fLastElement = newEl;
- LL->fNumElements++;
- }
- else
- { // add to non-empty list
- if (Index <= 1)
- { // add to beginning of list
- newEl->fNext = LL->fFirstElement;
- LL->fFirstElement->fPrev = newEl;
- LL->fFirstElement = newEl;
- }
- else if (Index > LLGetNumElements(LL))
- { // add to end of list
- newEl->fPrev = LL->fLastElement;
- LL->fLastElement->fNext = newEl;
- LL->fLastElement = newEl;
- }
- else
- { // add to middle of list
- short k;
- oldEl = LL->fFirstElement;
- for (k=1; (k<Index) && oldEl; k++)
- oldEl = (LLElPtr)oldEl->fNext;
- if (oldEl) // safe to reference it?
- {
- newEl->fPrev = oldEl->fPrev;
- newEl->fNext = oldEl;
- oldEl->fPrev = newEl;
- ((LLElPtr)oldEl->fPrev)->fNext = newEl;
- }
- }
- LL->fNumElements++;
- }
- }
- } // LLAddElementByIndex
-
-
- // ------------------------------------------------------------
- void LLAppendElement(LLHeadPtr LL, void * DataPtr)
- {
- if (LL)
- {
- LLAddElementByIndex(LL, DataPtr, LLGetNumElements(LL)+1);
- }
- } // LLAppendElement
-
-
- // ------------------------------------------------------------
- void LLDeleteElementByIndex(LLHeadPtr LL, short Index)
- {
- LLElPtr oldEl = NULL;
- if (LL)
- {
- if (LLGetNumElements(LL) > 0)
- { // non-empty list, OK to delete
- if (LLGetNumElements(LL) == 1)
- { // only one on list
- oldEl = LL->fFirstElement;
- LL->fFirstElement = NULL;
- LL->fLastElement = NULL;
- }
- else
- { // else more than one on list
- if (Index == 1)
- { // first one on list
- oldEl = LL->fFirstElement;
- ((LLElPtr)oldEl->fNext)->fPrev = NULL;
- LL->fFirstElement = (LLElPtr)oldEl->fNext;
- }
- else if (Index == LLGetNumElements(LL))
- { // last one on list
- oldEl = LL->fLastElement;
- LL->fLastElement = (LLElPtr)oldEl->fPrev; // move back
- LL->fLastElement->fNext = NULL;
- }
- else if ((Index > 1) && (Index < LLGetNumElements(LL)))
- { // middle of list
- short k;
- oldEl = LL->fFirstElement;
- for (k=1; (k<Index) && oldEl; k++)
- oldEl = (LLElPtr)oldEl->fNext;
- }
- } // else more than one on list
- // if found, delete it
- if (oldEl)
- {
- DisposePtr((Ptr)oldEl);
- LL->fNumElements--;
- }
- } // non-empty list, OK to delete
- }
- } // LLDeleteElementByIndex
-
-
- // Gets
-
- // ------------------------------------------------------------
- short LLGetMaxElements(LLHeadPtr LL)
- {
- if (!LL)
- return 0;
- else
- return LL->fMaxElements;
- } // LLGetMaxElements
-
-
- // ------------------------------------------------------------
- short LLGetNumElements(LLHeadPtr LL)
- {
- if (!LL)
- return 0;
- else
- return LL->fNumElements;
- } // LLGetNumElements
-
-
- // ------------------------------------------------------------
- void * LLGetElementByIndex(LLHeadPtr LL, short Index)
- {
- LLElPtr theEl = NULL;
- if (LL)
- {
- short k;
- theEl = LL->fFirstElement;
- for (k=1; (k<Index) && theEl; k++)
- theEl = (LLElPtr)theEl->fNext;
- }
- if (theEl)
- return theEl->fData;
- else
- return NULL;
- } // LLGetElementByIndex
-
-
- // ------------------------------------------------------------
- #ifdef LLTEST
- // ------------------------------------------------------------
-
- void LLTest(void)
- {
- char * p;
- short anError = 0;
- short k;
- LLHeadPtr LL = NULL;
-
- // pathological cases
- LLDeleteAllElements(LL);
- LLDestroyList(LL);
- LLAddElementByIndex(LL, NULL, 1);
- LLDeleteElementByIndex(LL, 1);
- p = LLGetElementByIndex(LL, 1);
- k = LLGetNumElements(LL);
- k = LLGetMaxElements(LL);
-
- // for real...
- LL = LLCreateList(10);
- if (LL == NULL)
- anError = -1;
- LLAddElementByIndex(LL, (char*)3, 1); // first ever
- LLAddElementByIndex(LL, (char*)1, 1); // insert at head
- LLAddElementByIndex(LL, (char*)4, 3); // append last
- LLAddElementByIndex(LL, (char*)2, 2); // add in middle
-
- p = LLGetElementByIndex(LL, 1);
- if ((long)p != 1)
- anError = 1;
- p = LLGetElementByIndex(LL, 2);
- if ((long)p != 2)
- anError = 2;
- p = LLGetElementByIndex(LL, 3);
- if ((long)p != 3)
- anError = 3;
- p = LLGetElementByIndex(LL, 4);
- if ((long)p != 4)
- anError = 4;
- p = LLGetElementByIndex(LL, 6);
-
- k = LLGetNumElements(LL);
- if (k != 4)
- anError = -4;
- k = LLGetMaxElements(LL);
- if (k != 10)
- anError = 10;
-
- LLDeleteElementByIndex(LL, 5); // bad
- LLDeleteElementByIndex(LL, 0);
-
- LLDeleteElementByIndex(LL, 4);
- LLDeleteElementByIndex(LL, 1);
- LLDeleteElementByIndex(LL, 2);
- LLDeleteElementByIndex(LL, 1);
-
- LLDeleteAllElements(LL);
- LLDestroyList(LL);
- } // LLTest
-
- #endif
-
-
-